/************************************************
 * Author       :   XXY
 * Blog         :   https://www.cnblogs.com/jzyl
 * Gitee        :   https://gitee.com/xiaobaichong
 * Email        :   1047185209@QQ.com
 * FileName     :   SceneBase.cs
 * CreateData   :   2023/4/28 14:49:30
 * UnityVersion :   2020.3.33f1c2
 * Description  :   场景_用于添加Entity_只有添加在Scene内的Entity才会执行
************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace Hotfix
{
    /// <summary>
    /// 场景_用于添加Entity_只有添加在Scene内的Entity才会执行
    /// </summary>
    internal class SceneBase : IScene
    {
        /// <summary>
        /// 场景是否是活跃状态
        /// </summary>
        private bool active = true;
        /// <summary>
        /// 如果场景运行中，则返回 true。
        /// </summary>
        public bool isLoaded
        {
            get
            {
                return active;
            }
        }
        /// <summary>
        /// 在该场景中的所有实体
        /// </summary>
        private Dictionary<string, EntityBase> entities = new Dictionary<string, EntityBase>();

        private bool AddEntity(EntityBase entity)
        {
            if (entities.ContainsKey(entity.Name))
            {
                LogUtillity.Error($"当前场景内已存在{entity.Name}实体");
                return false;
            }
            else
            {
                entities.Add(entity.Name, entity);
                Utility.SetPropertyValue(entity, "Scene", this);
                if (active)
                {
                    entity.OnInit();
                    Utility.SetPropertyValue(entity, "IsInit", true);
                    if (entity.Enable)
                    {
                        foreach (var system in entity.GetAllSystem)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.Awake);
                        }
                        foreach (var system in entity.GetAllSystem)
                        {
                            if (system.Enable)
                            {
                                system.SystemCallback.Emit(SystemCallbackType.OnEnable);
                            }
                        }
                        foreach (var system in entity.GetAllSystem)
                        {
                            if (system.Enable)
                            {
                                system.SystemCallback.Emit(SystemCallbackType.Start);
                            }
                        }
                    }
                }
                return true;
            }
        }

        public bool AddEntity<T>(string name) where T : EntityBase
        {
            Type type = typeof(T);
            T entity = (T)Activator.CreateInstance(type);
            Utility.SetPropertyValue(entity, "Name", name);
            return AddEntity(entity);
        }

        private bool RemoveEntity(EntityBase entity)
        {
            if (entities.Remove(entity.Name))
            {
                if (active)
                {
                    if (entity.Enable)
                    {
                        foreach (var system in entity.GetAllSystem)
                        {
                            if (system.Enable)
                            {
                                system.SystemCallback.Emit(SystemCallbackType.OnDisable);
                            }
                        }
                    }
                    foreach (var system in entity.GetAllSystem)
                    {
                        system.SystemCallback.Emit(SystemCallbackType.OnDestroy);
                    }
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool RemoveEntity(string entityName)
        {
            return RemoveEntity(this[entityName]);
        }
        public T GetEntity<T>(string name) where T : EntityBase
        {
            return (T)this[name];
        }
        /// <summary>
        /// 场景中实体数量
        /// </summary>
        public int Count
        {
            get
            {
                return entities.Count;
            }
        }
        /// <summary>
        /// 通过名称索引获取实体
        /// </summary>
        /// <param name="name">实体名称</param>
        /// <returns></returns>
        private EntityBase this[string name]
        {
            get
            {
                if (entities.ContainsKey(name))
                {
                    return entities[name];
                }
                else
                {
                    return null;
                }
            }
        }
        #region 场景周期函数
        public void Awake()
        {
            foreach (var entity in entities.Values)
            {
                if (!entity.IsInit)
                {
                    entity.OnInit();
                    Utility.SetPropertyValue(entity, "IsInit", true);
                }
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        system.SystemCallback.Emit(SystemCallbackType.Awake);
                    }
                }
            }
        }

        public void Start()
        {
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.Start);
                        }
                    }
                }
            }
        }

        public void OnEnable()
        {
            active = true;
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.OnEnable);
                        }
                    }
                }
            }
        }

        public void OnDisable()
        {
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.OnDisable);
                        }
                    }
                }
            }
            active = false;
        }

        public void Update()
        {
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.Update);
                        }
                    }
                }
            }
        }

        public void LateUpdate()
        {
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.LateUpdate);
                        }
                    }
                }
            }
        }

        public void FixedUpdate()
        {
            foreach (var entity in entities.Values)
            {
                if (entity.Enable)
                {
                    foreach (var system in entity.GetAllSystem)
                    {
                        if (system.Enable)
                        {
                            system.SystemCallback.Emit(SystemCallbackType.FixedUpdate);
                        }
                    }
                }
            }
        }

        public void OnDestroy()
        {
            foreach (var entity in entities.Values)
            {
                foreach (var system in entity.GetAllSystem)
                {
                    system.SystemCallback.Emit(SystemCallbackType.OnDestroy);
                }
            }
            active = false;
            // 清空实体
            entities.Clear();
        }
        #endregion
        #region 子类方法
        public virtual void OnInit()
        {

        }
        #endregion
    }
}